// 综合玩法插件
// 更新时间 2024年2月23日


string author = "Live";
string pluginName = "comprehensive 综合插件";
string version = "3.0";

//------------------------------游戏配置参数------------------------------
// 默认值（如果配置文件读取失败）

// 配置ID
int configID = 1;
// 开启复活？
bool openRespawn = true;
// 复活后带复活套装？
bool haveSuit = false;
// 复活的时间设置
int second = 30;
// 玩家的初始血量
int playerHealth = 100;
// 玩家商店是否打开？
bool shopOpen = true;
// 玩家商店类型（1是完全版，2是传送阉割版）
int shopType = 1;
// 无限备弹？
bool test_infiniteCollectedAmmo = true;
// 无限体力？
bool test_infiniteStamina = true;
// 僵尸锁人？
bool Horde = false;
// 僵尸常量
int zombieC = 0;
// 僵尸速度(true 全跑尸，false不变)
bool test_zombiespeed = false;
// 是否僵尸装扮
bool test_dress = false;
// 商店物品价格倍率
int mf = 1;
// 服务器名
string hostName = "[CN.Live] QQ群392635015";
// 地图集
string mapcycle = "mapcycle.txt";
// 难度
string Difficulty = 3;

//-------------------------------------------------------------------

// 数据库连接
CSQLConnection@ gMainConnection = null;

// 插件初始化
void OnPluginInit()
{
    // 设置插件信息
    PluginData::SetAuthor(author);
    PluginData::SetName(pluginName);
    PluginData::SetVersion(version);

    // 加载后提示信息
    ThePresident.InfoFeed("插件:"+pluginName+"| 版本:"+version+"| 作者:"+author,false);

    // 读取配置文件
    string configFileName = "noob";
    readConfig(configFileName);


    // 连接数据库
    ConnectToDB();

    // 设置地图集（实测无论是服务器配置文件还是启动参数又或是插件，必须在服务器启动后更换地图才会实际替换默认地图集）
    if(mapcycle != "mapcycle.txt")
        Engine.RunConsoleCommand( "mapcyclefile "+mapcycle );

    // 当玩家连接后
    Events::Player::OnPlayerConnected.Hook( @OnPlayerConnected );
    // 当没有存活的玩家时
    Events::ThePresident::OnNoSurvivorsRemaining.Hook( @OnNoSurvivorsRemaining );
    // 当玩家断开连接时
    Events::Player::OnPlayerDisconnected.Hook( @OnPlayerDisconnected );
    // 当玩家出生时
    Events::Player::OnPlayerSpawn.Hook( @OnPlayerSpawn );
    // 当玩家被杀死后
    Events::Player::OnPlayerKilledPost.Hook( @OnPlayerKilledPost );
    // 当玩家说
    Events::Player::PlayerSay.Hook( @PlayerSay );
    // 执行菜单项
    Events::Player::OnMenuExecuted.Hook( @OnMenuExecuted );
    // 当僵尸出生后
    Events::Infected::OnInfectedSpawned.Hook( @OnInfectedSpawned );
    // 感染者死亡
    Events::Infected::OnInfectedKilled.Hook( @OnInfectedKilled );
    // 防卫模式回合开始
    Events::FlatLine::WaveStart.Hook( @WaveStart );
    // 实体掉落
    Events::Player::OnEntityDropped.Hook( @OnEntityDropped );
    // 当玩家逃脱
    Events::Player::OnPlayerEscape.Hook( @OnPlayerEscape );
    // 当玩家抵达安全区
    Events::Player::OnPlayerReachSafeZone.Hook( @OnPlayerReachSafeZone );
    // 当玩家离开安全区
    Events::Player::OnPlayerLeftSafeZone.Hook( @OnPlayerLeftSafeZone );
    // 当回合终止时
    Events::ThePresident::OnTerminateRound.Hook( @OnTerminateRound );
    // 地图开始 
    ThePresident_OnMapStart();
}


// ------------------------------------配置文件读取方法------------------------------------

void readConfig(string configFileName){
    JsonValues@ JsonConfig = FileSystem::ReadFile(configFileName);
    // 读取所有参数
    configID = FileSystem::GrabInt(JsonConfig, "configID");
    if (configID == 0){
        ThePresident.InfoFeed("配置文件读取失败",false);
    }else{
        openRespawn = FileSystem::GrabBool(JsonConfig, "gameSetting","openRespawn");
        haveSuit = FileSystem::GrabBool(JsonConfig, "gameSetting","haveSuit");
        second = FileSystem::GrabInt(JsonConfig, "gameSetting","second");
        playerHealth = FileSystem::GrabInt(JsonConfig, "gameSetting","playerHealth");
        shopOpen = FileSystem::GrabBool(JsonConfig, "gameSetting","shopOpen");
        shopType = FileSystem::GrabInt(JsonConfig, "gameSetting","shopType");
        test_infiniteCollectedAmmo = FileSystem::GrabBool(JsonConfig, "gameSetting","test_infiniteCollectedAmmo");
        test_infiniteStamina = FileSystem::GrabBool(JsonConfig, "gameSetting","test_infiniteStamina");
        Horde = FileSystem::GrabBool(JsonConfig, "gameSetting","Horde");
        zombieC = FileSystem::GrabInt(JsonConfig, "gameSetting","zombieC");
        test_zombiespeed = FileSystem::GrabBool(JsonConfig, "gameSetting","test_zombiespeed");
        test_dress = FileSystem::GrabBool(JsonConfig, "gameSetting","test_dress");
        mf = FileSystem::GrabInt(JsonConfig, "gameSetting","mf");
        hostName = FileSystem::GrabString(JsonConfig, "gameSetting","hostName");
        mapcycle = FileSystem::GrabString(JsonConfig, "gameSetting","mapcycle");
        Difficulty = FileSystem::GrabString(JsonConfig, "gameSetting","Difficulty");
        
        ThePresident.InfoFeed("配置文件读取完毕",false);   
    }
}

//--------------------------------------数据库---------------------------------------------

// 连接数据库

void ConnectToDB()
{
    // SQL Connection info
    string strSQLHost = "localhost"; // Our hostname
    int iPort = 0; // if iPort is 0, then it will use default MySQL port
    string strSQLUser = "root"; // Our username
    string strSQLPass = "lingfeng"; // Our password
    string strSQLDB = "contagion"; // Our database

    // Create our connection
    SQL::Connect( strSQLHost, iPort, strSQLUser, strSQLPass, strSQLDB, OnSQLConnect );
}

void OnSQLConnect( CSQLConnection@ pConnection )
{
    if ( pConnection.Failed() ) {
        ThePresident.InfoFeed("数据库连接失败！",false);
    }
    
    @gMainConnection = pConnection;
    ThePresident.InfoFeed("数据库连接成功！",false);
    Chat.PrintToConsole(all, "{green}数据库连接成功！");
    Log.PrintToServerConsole(LOGTYPE_INFO, "Database connected...");
}

// 当插件卸载
void OnPluginUnload()
{
    // 关闭数据库连接
    SQL::Disconnect(gMainConnection);
}

// 地图关闭时关闭连接
void OnMapShutdown()
{
    saveALLMoney();
	SQL::Disconnect( gMainConnection );
}

// 地图初始化时，重新连接
void OnMapInit()
{
	@gMainConnection = null;
	ConnectToDB();
}

// -------------------------------------欢迎----------------------------------------------

// 当玩家连接后
HookReturnCode OnPlayerConnected(CTerrorPlayer@ pPlayer)
{
    // 欢迎玩家
    Chat.PrintToChat(all,"Server.{gold}[{green}Live{gold}]{white}:Welcome to my server{green}["+pPlayer.GetPlayerName()+"].");
    Chat.PrintToChat(all,"服务器.{gold}[{green}Live{gold}]{white}:欢迎你{green}["+pPlayer.GetPlayerName()+"]{white}来到我的服务器,欢迎进群交流：392635015");
    Chat.PrintToChat(all,"!b调出购买，!k自杀(!b menu,!k idioctonia)");
    // 控制台输出测试信息
    Chat.PrintToConsole(all,"[Live]插件测试信息:"+pPlayer.GetPlayerName()+" 加入游戏");
    Chat.PrintToConsole(all,"[Live]插件测试信息:"+pPlayer.GetPlayerName()+"的entindex是:"+pPlayer.entindex());

    DB_addPlayer(pPlayer);

    return HOOK_CONTINUE;
}

void DB_addPlayer(CTerrorPlayer@ pPlayer){
    string steamid = Utils.Steam64ToSteam32(pPlayer.GetSteamID64());
    // 创建数据库信息
    string sql_addPlayer = "INSERT INTO `record`(steamid,name) "
    "SELECT '"+steamid+"','"+pPlayer.GetPlayerName()+"' FROM DUAL "
    "WHERE NOT EXISTS("
	"SELECT steamid "
	"FROM `record` "
	"WHERE steamid = '"+steamid+"'"
    ");";
    //Chat.PrintToChat(all,sql_addPlayer);
    SQL::SendQuery( gMainConnection, sql_addPlayer, addPlayer );

    // 设置玩家金币，同步
    string sql_queryPlayer = "select * from `record` where steamid = '"+steamid+"';";
    SQL::SendQuery( gMainConnection, sql_queryPlayer, setPlayerMoney );
}

void addPlayer(IMySQL@ pQuery){
    // If our query is null, then it failed.
    if ( pQuery is null ) return;

    // That means the table does not exist. Let's create our table then.
    if ( !pQuery.Failed() )
    {
        //Chat.PrintToChat(all,"添加玩家信息成功！");
    }else{
        //Chat.PrintToChat(all,"添加玩家信息失败！");
    }
}

void setPlayerMoney(IMySQL@ pQuery){
    if( pQuery is null ) return;
    if( !pQuery.Failed() ){
        string steamid = SQL::ReadResult::GetString( pQuery, "steamid" );
        CTerrorPlayer@ pPlayer = GetPlayerBySteamID(steamid);
        // 归 0
        pPlayer.AddScore(-pPlayer.GetScore());
        int money = SQL::ReadResult::GetInt( pQuery, "money" );
        pPlayer.AddScore(money);
        Log.PrintToServerConsole(LOGTYPE_INFO, "money---Synchronized");
    }
}

// -------------------------------------复活----------------------------------------------

// Gamemodes
// 这是官方设定的地图模式所对应的数字，即匹配下方全部玩家死亡方法的iCandidate。
const int GM_NONE = 0;				// If our gamemode wasn't found, or just dev_ maps
const int GM_ESCAPE = 1;			// Escape maps (ce_)
const int GM_EXTRACTION = 2;		        // Extraction maps (cx_)
const int GM_FLATLINE = 3;			// Flatline maps (cf_)
const int GM_HUNTED = 4;			// Hunted maps (ch_)
const int GM_PANIC = 5;				// Panic maps (cp_)

// 游戏结束标识位（如果游戏结束，终止复活）
bool gameover = false;

// 玩家复活倒计时数组
// 因为官方提供的Schedule::Task计时方法只能接受一个参数并且必须是int，再加上其运行特殊性，无法同时传递计时和玩家槽位id
// 我的想法是，以玩家槽位ID作为索引对应该数组元素为复活时间，即如果entindex()为x，则它使用respawnSecondp[x-1]（因为entindex从1开始。数组索引从0开始）作为该玩家的复活时间
// （一个玩家一个位置，可按照最大人数自行更改，此处为20个）


const array<int> respawnSecondConst = {second,second,second,second,second,second,second,second,second,second,second,second,second,second,second,second,second,second,second,second}; 
array<int> respawnSecond = respawnSecondConst;
// 这个数组是用来解决BUG问题的，复活标识，0 不能复活 1 能复活，防止因为各种正在复活时的突发重生行为（玩家被命令重生，防守模式中回合胜利的自动重生）
// 从而导致复活后倒计时复活还在运作导致再复活一次的BUG
array<bool> canRespawn = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false};
 

// 当幸存者玩家全部死亡
HookReturnCode OnNoSurvivorsRemaining( int iCandidate )
{
    // 匹配游戏模式，阻断默认的游戏结束事件（测试用）
	// If objective, then no game over
	// if ( iCandidate == GM_ESCAPE ) return HOOK_HANDLED;
    // if ( iCandidate == GM_FLATLINE ) return HOOK_HANDLED;
	// if ( iCandidate == GM_PANIC ) return HOOK_HANDLED;
	// if ( iCandidate == GM_EXTRACTION ) return HOOK_HANDLED;

    // 幸存者玩家全部死亡,中断所有复活方法（注释后游戏结束也不会停止复活，配合上方游戏结束事件使用，方便个人测试）
    gameover = true;
    // 输出测试信息
    Chat.PrintToConsole(all,"[Live]插件测试信息: 团灭失败");
    //重置复活计时数组，防止因游戏结束后部分玩家复活停止导致的数据变化
    respawnSecond = respawnSecondConst;
	return HOOK_CONTINUE;
}

// 当玩家断开连接后
HookReturnCode OnPlayerDisconnected(CTerrorPlayer@ pPlayer)
{
    if ( pPlayer is null ) 
        return HOOK_HANDLED;
    int index = pPlayer.entindex();
    // 将复活标识设为false,防止BUG
    canRespawn[index-1] = false;
    // 重置掉该玩家槽位的复活时间
    respawnSecond[index-1] = second;
    // 控制台输出测试信息
    //Chat.PrintToConsole(all,"[Live]插件测试信息:"+pPlayer.GetPlayerName()+" 退出游戏");
	return HOOK_CONTINUE;
}


//当玩家重生时
HookReturnCode OnPlayerSpawn(CTerrorPlayer@ pPlayer)
{
    if ( pPlayer is null ) 
        return HOOK_HANDLED;
    // 获取当前重生体的身份
    // 如果是人复活重生了
    if ( pPlayer.GetTeamNumber() == TEAM_SURVIVOR ){
        // 将复活标识设为false，防止因其它因素复活（命令复活、守卫模式回合复活）后还在倒计时复活的BUG
        int index = pPlayer.entindex();
        canRespawn[index-1] = false;
        // 重置复活时间
        respawnSecond[index-1] = second;
        // 给装备
        GivePlayerWeapon(pPlayer);
        // 重置血量(防止连续图复活血量不完整)
        if(not (playerHealth == 100)){
            pPlayer.SetMaxHealth(playerHealth);
            pPlayer.SetHealth(pPlayer.GetMaxHealth());
        }else{
            pPlayer.SetHealth(pPlayer.GetMaxHealth());
        }
    }else{
        // 获取当前的游戏模式
        int gamemode = ThePresident.GetGameModeType();
        // 这个游戏中途加入的人会变成小强或者丧尸，为了让其复活
        // 如果游戏不是猎杀模式
        if( not (gamemode == CT_HUNTED) ){
            // 延时5秒调用检查方法，防止死亡的玩家一瞬间变成旁观者（守卫模式），复活时间还是second秒没来得及减少导致判断错误的BUG
            Schedule::Task(5.0f,pPlayer.entindex(),check);
        }
    }
	return HOOK_CONTINUE;
}

// 用于检查玩家是否是不能复活的玩家
void check(int index){
    CTerrorPlayer@ pPlayer = ToTerrorPlayer( index );
    // 获取当前玩家的身份
    int TeamNumber = pPlayer.GetTeamNumber();
    //Chat.PrintToChat(all,""+TeamNumber);
    // 如果当前玩家身份是旁观者或者丧尸（再判断一次，防止是0）
    if(TeamNumber == TEAM_SPECTATOR || TeamNumber == TEAM_ZOMBIE){
        // 先判断是否开启了复活
        if( openRespawn ){
            // 判断该角色的复活时间是不是second（正在复活会减少时间，调用前已延迟5秒防止速度太快误判），即可分辨是死亡后正在复活的小强或者丧尸，还是中途进入没在复活的小强
            if(respawnSecond[index-1] == second){
                if(!gameover){
                    // 复活玩家
                    respawnPlayer(index);
                    Chat.PrintToChat(all, "{gold}[{green}Live{gold}]{white}:检测到玩家["+pPlayer.GetPlayerName()+"]加入时为小强或丧尸，已自动得到重新做人的机会" );
                }
            }
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}当前模式为硬核模式，复活关闭，请耐心等待队友，不要退出游戏(Resurrection closed, waiting for teammates to die or escape)....");
        }
    }
}


//当玩家死亡后
HookReturnCode OnPlayerKilledPost(CTerrorPlayer@ pPlayer)
{
    if ( pPlayer is null ) 
        return HOOK_HANDLED;
    // 输出提示信息
    Chat.CenterMessage(all,"["+pPlayer.GetPlayerName()+"]的屁股被丧尸给撅了...(["+pPlayer.GetPlayerName()+"]has died)");
    // 输出测试信息
    Chat.PrintToConsole(all,pPlayer.GetPlayerName()+" 死亡");
    //Chat.PrintToConsole(all,"[Live]插件测试信息(respawnSecond):"+respawnSecond[0]+respawnSecond[1]+respawnSecond[2]+respawnSecond[3]+respawnSecond[4]+respawnSecond[5]+respawnSecond[6]+respawnSecond[7]);
    Chat.PrintToConsole(all,"[Live]插件测试信息(index):"+pPlayer.entindex());
    // 如果开启了复活
    if( openRespawn ){
        // 获取玩家身份
        int TeamNumber = pPlayer.GetTeamNumber();
        // 是人才给复活，防止BUG
        if(TeamNumber == TEAM_SURVIVOR){
            int index = pPlayer.entindex();
            // 设置复活标识位为真
            canRespawn[index-1] = true; 
            // 开始倒计时方法
            Schedule::Task( 0.0f, pPlayer.entindex(), tip );
        }
    }
    return HOOK_CONTINUE;
}


//提示死亡计时
void tip(int index){ 
    // 游戏是否结束
    if( not gameover ){
        // 该玩家的复活标识位，以便其它事件随时终止复活
        if( canRespawn[index-1] ){
            // 倒计时提示玩家
            CBasePlayer@ pPlayer = ToBasePlayer( index );
            Chat.CenterMessagePlayer(pPlayer,respawnSecond[index-1]+"秒后复活...(Waiting for resurrection "+respawnSecond[index-1]+")");
            // 递减该玩家对应数组中的时间
            respawnSecond[index-1]--;
            // 倒计时还大于-1秒就继续调用
            if(respawnSecond[index-1] > -1 )
                // 这里做了一个递归函数（因为我发现官方的Task方法很奇怪，当使用循环时，会将时间和结果堆叠在一起并在一个方法结束后输出）
                // 每一秒调用一次计时方法
                Schedule::Task(1.0f,index,tip);
            else{
                // 倒计时归零，结束递归，转调用复活玩家的方法
                respawnPlayer(index);
            }
        }
    }
}

//复活玩家
void respawnPlayer(int index){
    //重置被复活玩家的复活时间值
    respawnSecond[index-1] = second;
    CTerrorPlayer@ pPlayer = ToTerrorPlayer( index );
    if ( pPlayer is null ) return;
    // 修改被复活玩家的游戏阵营
    pPlayer.ChangeTeam( TEAM_SURVIVOR );
    // 复活玩家
    pPlayer.Respawn();
    // 提示玩家复活
    Chat.CenterMessage(all, "["+pPlayer.GetPlayerName()+"]从石头里蹦出来了！(["+pPlayer.GetPlayerName()+"]has been resurrected)");
    // 输出测试信息
    Chat.PrintToConsole(all,"[Live]插件测试信息:"+pPlayer.GetPlayerName()+" 复活");
}

// 给装备方法
void GivePlayerWeapon(CTerrorPlayer@ pPlayer){
    if(pPlayer is null) return;
    int index = pPlayer.entindex();
    // 如果-1，不发装备
    if( playerSuitList[index-1] == -1 ) return;
    // 清空所有
    pPlayer.StripEquipment( true );
    // 给手机
    pPlayer.GiveWeapon( "phone" );
    // 给一个便携式手电
    pPlayer.GiveWeapon( "plight" );
    // 给子弹
    pPlayer.GiveWeapon( "ammo" );
    // 套装1 手枪套
    if( playerSuitList[index-1] == 0){
        // 给小刀
        pPlayer.GiveWeapon( "kabar" );
        // 给手枪
        pPlayer.GiveWeapon( "sig" );  
    // 套装2 沙鹰套
    }else if( playerSuitList[index-1] == 1 ){
        // 给斧头
        pPlayer.GiveWeapon( "Fireaxe" );
        // 给沙鹰
        pPlayer.GiveWeapon( "handcannon" );
    // 套装3 近战套
    }else if( playerSuitList[index-1] == 2 ){
        // 给医疗包
        pPlayer.GiveWeapon( "firstaid" );
        // 给砍刀
        pPlayer.GiveWeapon( "machete" );
    // 套装4 莫泊莫斯套
    }else if( playerSuitList[index-1] == 3 ){
        // 给扳手
        pPlayer.GiveWeapon( "Wrench" );
        // 给莫泊莫斯
        pPlayer.GiveWeapon( "Mossberg" );
    // 套装5 连喷套
    }else if( playerSuitList[index-1] == 4 ){
        // 给棒球棒
        pPlayer.GiveWeapon( "Baseballbat" );
        // 给连喷
        pPlayer.GiveWeapon( "Autoshotgun" );
    // 套装6 弓箭套
    }else if( playerSuitList[index-1] == 5 ){
        // 给键盘
        pPlayer.GiveWeapon( "Keyboard" );
        // 给弓箭
        pPlayer.GiveWeapon( "compbow" );
    }
}


//--------------------------------------玩家命令--------------------------------

// 当玩家say
HookReturnCode PlayerSay(CTerrorPlayer@ pPlayer, CASCommand@ pArgs)
{
	string arg = pArgs.Arg( 1 );
	string arg1 = "";
	string arg2 = "";

	// 切分字符串(这样就可以用空格传一个命令参数了)
	int subIndex = arg.findFirst(" ",0);
	if(not (subIndex < 0)){
		arg1 = arg.substr(0,subIndex);
		arg2 = arg.substr(subIndex+1,-1);
		//Chat.PrintToChat(all,""+arg1+"|"+arg2);
	}else{
		arg1 = arg;
	}

    // 自杀
	if( Utils.StrEql( arg1, "!k" ) ){
        if(Utils.StrEql( arg2, "" )){
            int TeamNumber = pPlayer.GetTeamNumber();
            if(TeamNumber == 2){
                Engine.RunConsoleCommand( "admin slay !" + pPlayer.entindex() );
                return HOOK_HANDLED;
            }else{
                Chat.PrintToChat(pPlayer,"{gold}[{green}Server{gold}]{white}:只有做人的时候才能自杀！（Suicide is only possible when in the survivor camp）");
            }
        }else if(arg2 == "all"){
            if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN)){
                playerList = Utils.CollectPlayers();
                for(uint i=0;i<playerList.length();i++){
                    CTerrorPlayer@ player = ToTerrorPlayer(playerList[i]);
                    if(player.GetTeamNumber() == TEAM_SURVIVOR){
                        Engine.RunConsoleCommand( "admin slay !" + playerList[i] );
                    }
                }
                Chat.PrintToChat(all,"{red}毁灭吧！");
            }else{
                Chat.PrintToChat(pPlayer,"{hotpink}只有超级管理员能用");
            }
        }
    // 复活
	}else if( Utils.StrEql( arg1, "!fh" ) ){
        // 得是管理员
		if( AdminSystem.AdminExist(pPlayer) ){
			if( not Utils.StrEql( arg2, "" ) ){
                if( arg2 == "all" ){
                    playerList = Utils.CollectPlayers();
                    for(uint i=0;i<playerList.length();i++){
                        CTerrorPlayer@ player = ToTerrorPlayer(playerList[i]);
                        if(not (player.GetTeamNumber() == TEAM_SURVIVOR)){
                            respawnPlayer(playerList[i]);
                        }
                    }
                    Chat.PrintToChat(all,"管理员复活了所有玩家");
                }else{
                    CTerrorPlayer@ splayer = ToTerrorPlayer( parseInt(arg2,10,0) );
                    if(splayer is null) return HOOK_CONTINUE;
                    // 修改被复活玩家的游戏阵营
                    splayer.ChangeTeam( TEAM_SURVIVOR );
                    // 复活玩家
                    splayer.Respawn();
                    Chat.PrintToChat(all,"{hotpink}管理员使用命令复活了["+splayer.GetPlayerName()+"]");
                }
			}else{
				// 修改被复活玩家的游戏阵营
				pPlayer.ChangeTeam( TEAM_SURVIVOR );
				// 复活玩家
				pPlayer.Respawn();
			}
		}else{
			Chat.PrintToChat(pPlayer,"您不是管理员，无法执行复活命令");
		}
	}else if( Utils.StrEql( arg1, "!b" ) ){
        // 如果商店开启
        if(shopOpen){
            MAINSHOP(pPlayer);
            //Chat.PrintToChat(pPlayer,"因为官方的BUG，购买物品{hotpink}必须要留两个格子\n（Because the official API provided has bug, you {hotpink}must have two free backpack spaces）");
            Chat.PrintToChat(pPlayer,"当前的金币为:{hotpink}"+pPlayer.GetScore());
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}管理员未开启商店");
        }
	}else if(Utils.StrEql( arg1, "!t" )){
        // 如果是管理员
        if(AdminSystem.AdminExist(pPlayer)){     
            // 超级管理员
            if(AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN)){
                superAdminMenu(pPlayer);
            // 管理员
            }else if(AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_ADMIN)){
                adminMenu(pPlayer);
            // 主持人
            }else if(AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_MODERATOR)){
                moderatorMenu(pPlayer);
            }
        }else{
            Chat.PrintToChat(pPlayer,"成为管理员才能使用管理菜单（Becoming an administrator is necessary to use the management menu）");
        }
    }else if( Utils.StrEql( arg1, "!g" ) ){
        if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN )){
            CASConVarRef@  god = ConVar::Find( "god" );
            if(god is null) return HOOK_CONTINUE;
            if(isGod){
                god.SetValue("0");
                Chat.PrintToChat( pPlayer,"{hotpink}全员无敌已关闭");
            }else{
                god.SetValue("1");
                Chat.PrintToChat( pPlayer,"{hotpink}全员无敌已开启");
            }
            isGod = !isGod;
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}超级管理员才能用");
        }
    }else if(arg1 == "!give"){
        if( AdminSystem.AdminExist(pPlayer) ){
            if(not Utils.StrEql( arg2, "" )){
                pPlayer.GiveWeapon(arg2);
            }else{
                Chat.PrintToChat(pPlayer,"需要输入武器名");
            }
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}管理员才能用");
        }
    }else if(arg1 == "!z"){
        if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN )){
            if( not Utils.StrEql( arg2, "" ) ){
                ThePresident.SpawnZombies(parseInt(arg2,10,0));
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"生成了"+arg2+"只丧尸");
            }else{
                Chat.PrintToChat(pPlayer,"需要输入僵尸数量");
            }
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}超级管理员才能用");
        }
    }else if(arg1 == "!zc"){
        if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN )){
            if( not Utils.StrEql( arg2, "" ) ){
                ThePresident.SetSpawnConstantFlags(ZSF_FORCED_NEAR_SPAWN);
                ThePresident.SetSpawnZombiesConstant(parseInt(arg2,10,0));
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"设置丧尸常量"+arg2+"只");
                zombieC = parseInt(arg2,10,0);
            }else{
                Chat.PrintToChat(pPlayer,"需要输入僵尸数量");
            }
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}超级管理员才能用");
        }
    }else if(arg1 == "!zac"){
        if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN )){
            if( not Utils.StrEql( arg2, "" ) ){
                ThePresident.SetSpawnConstantFlags(ZSF_FORCED_NEAR_SPAWN);
                ThePresident.SpawnZombiesConstant(parseInt(arg2,10,0));
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"设置丧尸增加常量"+arg2+"只");
            }else{
                Chat.PrintToChat(pPlayer,"需要输入僵尸常量增加数量");
            }
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}超级管理员才能用");
        }
    }else if(arg1 == "!ph"){
        if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN )){
            if( not Utils.StrEql( arg2, "" ) ){
                playerHealth = parseInt(arg2,10,0);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"设置玩家出生血量为："+arg2);
            }else{
                Chat.PrintToChat(pPlayer,"需要输入想设置的玩家血量");
            }
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}超级管理员才能用");
        } 
    }else if(arg1 == "!ff"){
        if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN )){
            if( arg2 == "0" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_types 0" );
                Chat.PrintToChat(pPlayer,"{hotpink}开启友伤");
            }else if( arg2 == "1" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_types 1" );
                Chat.PrintToChat(pPlayer,"{hotpink}关闭友伤");
            }else if( arg2 == "2" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_types 2" );
                Chat.PrintToChat(pPlayer,"{hotpink}开启反伤");
            }
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}超级管理员才能用");
        }
    }else if(arg1 == "!ffd"){
        if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN )){
            CASConVarRef@ casDifficulty = ConVar::Find( "difficulty" );
            string difficulty = casDifficulty.GetValue();
            Chat.PrintToChat(all,"{hotpink}当前难度为："+difficulty);
            // 根据不同难度修改对应参数
            if( difficulty == "0" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_easy "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }else if( difficulty == "1" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_normal "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }else if( difficulty == "2" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_hard "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }else if( difficulty == "3" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_extreme "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }else if( difficulty == "4" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_nightmare "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}超级管理员才能用");
        }
        
    }else if(arg1 == "!config"){
        if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN )){
            if(arg2 != ""){
                readConfig(arg2);
                ThePresident_OnMapStart();
                Chat.PrintToChat(all,"{hotpink}更换配置文件完成");
            }else{
                Chat.PrintToChat(pPlayer,"{hotpink}请输入正确的配置文件名");
            }
        }else{
            Chat.PrintToChat(pPlayer,"{hotpink}超级管理员才能用");
        }
    }else if( arg1 == "!h" ){
        string tip1 = "{red}!h 输出命令提示\n!k 自杀 !k all 杀所有玩家\n!b 菜单\n!give ? 获得对应武器\n";
        string tip2 = "{red}!z ? 生成僵尸\n!zc ? 设置僵尸常量\n!zac ? 增加僵尸常量\n!ph ? 设置玩家出生血量\n";
        string tip3 = "{red}!fh 复活自己 !fh ? 复活玩家\n!fh all 复活所有死亡玩家\n!k all 杀死所有存活玩家\n";
        string tip4 = "{red}!ff ? 友伤（0 队友伤害 1 禁用 2 反伤）\n!ffd ? 友伤倍率\n!gm ? 注意，以上命令大部分为管理员特有";
        Chat.PrintToChat(pPlayer,tip1);
        Chat.PrintToChat(pPlayer,tip2);
        Chat.PrintToChat(pPlayer,tip3);
        Chat.PrintToChat(pPlayer,tip4);
    // }else if( arg1 == "!sql" ){
    //     DB_addPlayer(pPlayer);
    // }else if( arg1 == "!esc"){
    //     pPlayer.Escape();
    }else if( arg == "!join" ){
        DB_addPlayer(pPlayer);
    // }else if( arg == "!save" ){
    //     saveMoney(pPlayer);
    // }else if( arg == "!test" ){
    //     test();
    }
	return HOOK_CONTINUE;
}

void MAINSHOP(CTerrorPlayer@ pPlayer){
    if(shopType == 1){
        Menu_PlayerShop(pPlayer);
    }else if(shopType ==2){
        Menu_PlayerShop2(pPlayer);
    }
}

void Menu_PlayerShop( CTerrorPlayer@ pPlayer ){
	if (pPlayer is null ) return;
    Menu pMenu;
	pMenu.SetID( "Menu_PlayerShop" );
	pMenu.SetTitle( "商店" );
	pMenu.AddItem( "复活队友（"+10*mf+"） Revival of teammates" );
    pMenu.AddItem( "复活自己（"+25*mf+"） Revive oneself" );
    pMenu.AddItem( "传送(free) tp" );
    pMenu.AddItem( "医疗包（"+8*mf+"） firstaid" );
    pMenu.AddItem( "手雷（"+6*mf+"） grenade" );
    pMenu.AddItem( "选择复活套装" );
	pMenu.Display( pPlayer, -1 );
}

void Menu_PlayerShop2( CTerrorPlayer@ pPlayer ){
	if (pPlayer is null ) return;
    Menu pMenu;
	pMenu.SetID( "Menu_PlayerShop2" );
	pMenu.SetTitle( "商店" );
    pMenu.AddItem( "传送(free) tp" );
	pMenu.Display( pPlayer, -1 );
}

// 玩家列表
array<int> playerList = {};

// 打开玩家传送菜单（index从0开始）
void Open_PlayerShop_Tele(CTerrorPlayer@ pPlayer){
    Menu_PlayerShop_Tele(pPlayer,0);
}

// 玩家传送菜单
void Menu_PlayerShop_Tele(CTerrorPlayer@ pPlayer,int index){
    if (pPlayer is null ) return;
    playerList = Utils.CollectPlayers();
    Menu pMenu;
	pMenu.SetID( "Menu_PlayerShop_Tele_Select;"+index );
	pMenu.SetTitle( "传送" );
    // 内容填充方法（填充玩家）
    Player_ItemFill(pPlayer,pMenu,index);
}

// 内容填充方法，从index开始
void Player_ItemFill(CTerrorPlayer@ pPlayer,Menu pMenu,int index){
    // 计数
    int count = 0;
    for(uint i=index;i<playerList.length();i++){
        CBasePlayer@ player = ToBasePlayer(playerList[i]);
        pMenu.AddItem(""+player.GetPlayerName());
        // 因为菜单一页只能有七个
        if(count>6) break;
        count++;
    }
    pMenu.SetBack( true );
    // 如果大于7项，就有下一页按钮
    if(count>6){
        pMenu.SetNext( true );
    }
    pMenu.Display( pPlayer, -1 );
}

// 初始化玩家复活套装列表
int defaultSuit = -1;
const array<int> playerSuitListConst = {defaultSuit,defaultSuit,defaultSuit,defaultSuit,
defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,
defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit};

array<int> playerSuitList = playerSuitListConst;

void Menu_SelectSuit( CTerrorPlayer@ pPlayer ){
    Menu pMenu;
    pMenu.SetID( "Menu_SelectSuit" );
    pMenu.SetTitle( "@选择复活套装@\nselect respawn suit" );
    pMenu.AddItem( "手枪套 sig" );
    pMenu.AddItem( "Mossberg喷子套" );
    pMenu.AddItem( "近战套 Machete" );
    pMenu.AddItem( "弓箭套 bow" );
    pMenu.AddItem( "关闭复活套装 close" );
    pMenu.Display( pPlayer, -1 );
}

//-----------------------------------管理员菜单-----------------------------------

// 是否冻结
bool test_freeze = false;
// 是否全员上帝
bool isGod = false;
// 无限主弹
bool test_infiniteAmmo = false;
// 显示僵尸速度
bool test_checkZS = false;
// 持续输出僵尸数量
bool test_getZombieNum = false;
// 作弊
bool test_cheats = false;

//僵尸出生后
HookReturnCode OnInfectedSpawned(Infected@ pInfected)   
{
    if ( pInfected is null ) return HOOK_CONTINUE;
    if (test_zombiespeed)
        pInfected.SetAnimationSet(10);
    if( test_checkZS )
        Chat.PrintToChat(all,"生成的僵尸速度为："+pInfected.GetAnimationSet());
    if (test_dress){
        // 如果不带防爆头盔
        if (not pInfected.HasRiotHelmet()){
            // 套个南瓜头 
            Utils.CosmeticWear( pInfected, "models/halloween/w_head_pumpkin.mdl" );
        }
    }
	return HOOK_CONTINUE;
}

// 主持
void moderatorMenu(CTerrorPlayer@ pPlayer){
    Chat.PrintToChat(pPlayer,"主持菜单");
}

// 管理员
void adminMenu(CTerrorPlayer@ pPlayer){
    Chat.PrintToChat(pPlayer,"管理员菜单");
}

// 超级管理员
void superAdminMenu(CTerrorPlayer@ pPlayer){
    if ( pPlayer is null ) return;
    Menu pMenu;
	pMenu.SetID( "superAdminMenu" );
	pMenu.SetTitle( "@超级管理员菜单@" );
    pMenu.AddItem( "武器" );
    pMenu.AddItem( "僵尸" );
    pMenu.AddItem( "地图" );
    pMenu.AddItem( "道具" );
    pMenu.AddItem( "玩家" );
    pMenu.AddItem( "服务器" );
    pMenu.AddItem( "其它" );
	pMenu.Display( pPlayer, -1 );
}

// 武器菜单
void Menu_Weapon(CTerrorPlayer@ pPlayer){
    if( pPlayer is null ) return;
    Menu pMenu;
	pMenu.SetID( "Menu_Weapon" );
	pMenu.SetTitle( "@武器@\n（其它武器!give）" );
    pMenu.AddItem( "医疗包" );
	pMenu.AddItem( "连喷" );
	pMenu.AddItem( "m4" );  
	pMenu.AddItem( "沙鹰" );
	pMenu.AddItem( "榴弹枪" );
    pMenu.AddItem( "添加子弹" );
    pMenu.AddItem( "手雷" );
    pMenu.SetBack( true );
    pMenu.SetNext( true );
    pMenu.Display( pPlayer, -1 );
}

// 武器菜单2
void Menu_Weapon2(CTerrorPlayer@ pPlayer){
    if( pPlayer is null ) return;
    Menu pMenu;
	pMenu.SetID( "Menu_Weapon2" );
	pMenu.SetTitle( "@武器2@\n（其它武器!give）" );
    pMenu.AddItem( "获取当前武器类名" );
    pMenu.AddItem( "秒杀手枪" );
    pMenu.AddItem( "火焰喷射器" );
    pMenu.AddItem( "获取喷子套" );
    pMenu.SetBack( true );
    pMenu.Display( pPlayer, -1 );
}

// 僵尸菜单
void Menu_Zombie(CTerrorPlayer@ pPlayer){
    if( pPlayer is null ) return;   
    Menu pMenu;
	pMenu.SetID( "Menu_Zombie" );
	pMenu.SetTitle( "@僵尸@" );
    pMenu.AddItem( "当前僵尸数量" );
    pMenu.AddItem( "持续检查僵尸数量" );
    pMenu.AddItem( "Horde模式" );
    pMenu.AddItem( "清除僵尸" );
    pMenu.AddItem( "冻结/重新冻结僵尸" );
    pMenu.AddItem( "解冻僵尸" );
    pMenu.SetBack( true );
    pMenu.SetNext( true );
    pMenu.Display( pPlayer, -1 );
}

// 僵尸菜单2
void Menu_Zombie2(CTerrorPlayer@ pPlayer){
    if( pPlayer is null ) return;   
    Menu pMenu;
	pMenu.SetID( "Menu_Zombie2" );
	pMenu.SetTitle( "@僵尸2@" );
    pMenu.AddItem( "跑尸/走尸" );
    pMenu.AddItem( "显示生成的僵尸速度" );
    pMenu.SetBack( true );
    pMenu.Display( pPlayer, -1 );
}

// 地图菜单
void Menu_Map(CTerrorPlayer@ pPlayer){
    if( pPlayer is null ) return;   
    Menu pMenu;
	pMenu.SetID( "Menu_Map" );
    pMenu.SetTitle( "@地图@" );
    pMenu.AddItem( "更换地图" );
    pMenu.AddItem( "重开" );
    pMenu.AddItem( "当前地图类型" );
    pMenu.AddItem( "当前地图名" );
    pMenu.SetBack( true );
    pMenu.Display( pPlayer, -1 );
}

// 更换地图 子菜单
array<string> mapList = {};

void Open_Menu_Selct(CTerrorPlayer@ pPlayer){
    Menu_Map_Select(pPlayer,0);
}

void Menu_Map_Select(CTerrorPlayer@ pPlayer,int index){
    Globals.GetMaps(mapList);
    Menu pMenu;
    pMenu.SetID("Menu_Map_Select;"+index);
    pMenu.SetTitle("@选择要更换的地图@");
    int count = 0;
    for(uint i=index;i<mapList.length();i++){
        pMenu.AddItem(mapList[i]);
        if( count>6 ) break;
        count++;
    }
    pMenu.SetBack( true );
    if( count>6 )
        pMenu.SetNext( true );
    pMenu.Display(pPlayer,-1);
}

// 道具菜单
void Menu_Prop(CTerrorPlayer@ pPlayer){
    if( pPlayer is null ) return;   
    Menu pMenu;
	pMenu.SetID( "Menu_Prop" );
    pMenu.SetTitle( "@道具@" );
    pMenu.AddItem( "钥匙" );
    pMenu.AddItem( "卡片" );
    pMenu.AddItem( "钳子" );
    pMenu.AddItem( "喷灯" );
    pMenu.AddItem( "便携式手电" );
    pMenu.AddItem( "灭火器" );
    pMenu.AddItem( "防毒面具" );
    pMenu.SetBack( true );
    pMenu.Display( pPlayer, -1 );
}

// 打开玩家菜单
void Open_Menu_Player(CTerrorPlayer@ pPlayer){
    Menu_Player(pPlayer,0);
}

// 玩家菜单
void Menu_Player(CTerrorPlayer@ pPlayer,int index){
    if(pPlayer is null) return;
    playerList = Utils.CollectPlayers();
    Menu pMenu;
    pMenu.SetID( "Menu_Player;"+index );
    pMenu.SetTitle( "@选择玩家@" );
    int count = 0;
    for(uint i=index;i<playerList.length();i++){
        CBasePlayer@ player = ToBasePlayer(playerList[i]);
        pMenu.AddItem(""+player.GetPlayerName());
        if(count>6) break;
        count++;
    }
    pMenu.SetBack( true );
    if(count>6){
        pMenu.SetNext( true );
    }
    pMenu.Display( pPlayer, -1 );
}

// 玩家菜单子选项
void Player_Option(CTerrorPlayer@ pPlayer,int pPlayerIndex){
    CTerrorPlayer@ cPlayer = ToTerrorPlayer(pPlayerIndex);
    Menu pMenu;
    pMenu.SetID( "Player_Option1;"+pPlayerIndex);
    pMenu.SetTitle("对玩家["+cPlayer.GetPlayerName()+"]操作");
    pMenu.AddItem("血量增幅");
    pMenu.AddItem("杀死该玩家");
    pMenu.AddItem("传送到自己");
    pMenu.AddItem("发武器套装1");
    pMenu.AddItem("添加管理员");
    pMenu.AddItem("删除管理员");
    pMenu.AddItem("增加金钱");
    pMenu.SetBack( true );
    pMenu.SetNext( true );
    pMenu.Display( pPlayer, -1 );
}

// 玩家菜单子选项2
void Menu_Player_option2(CTerrorPlayer@ pPlayer,int pPlayerIndex){
    CTerrorPlayer@ cPlayer = ToTerrorPlayer(pPlayerIndex);
    Menu pMenu;
    pMenu.SetID( "Player_Option2;"+pPlayerIndex );
    pMenu.SetTitle("对玩家["+cPlayer.GetPlayerName()+"]操作");
    pMenu.AddItem("踢出玩家");
    pMenu.AddItem("ban");
    pMenu.SetBack( true );
    pMenu.Display( pPlayer, -1 );
}

// 服务器菜单
void Menu_Server(CTerrorPlayer@ pPlayer){
    Menu pMenu;
    pMenu.SetID( "Menu_Server" );
    pMenu.SetTitle("服务器设置");
    pMenu.AddItem("作弊");
    pMenu.AddItem("无限体力");
    pMenu.AddItem("无限备弹");
    pMenu.AddItem("无限主弹");
    pMenu.AddItem("强制游戏获胜");
    pMenu.AddItem("开启人机");
    pMenu.AddItem("添加人机");
    pMenu.SetBack( true );
    pMenu.Display( pPlayer, -1 );
}

// 其它菜单
void Menu_Other(CTerrorPlayer@ pPlayer){
    if( pPlayer is null ) return;   
    Menu pMenu;
	pMenu.SetID( "Menu_Other" );
    pMenu.SetTitle( "其它测试" );
    pMenu.AddItem( "僵尸装扮" );
    pMenu.AddItem( "开关复活" );
    pMenu.AddItem( "开启/关闭自定义套装" );
    pMenu.AddItem( "加分" );
    pMenu.AddItem( "选择自定义套装" );
    pMenu.AddItem( "清除地图子弹" );
    pMenu.SetBack( true );
    pMenu.SetNext( true );
    pMenu.Display( pPlayer, -1 );                       
}

// 其它菜单2
void Menu_Other2(CTerrorPlayer@ pPlayer){
    if( pPlayer is null ) return;
    Menu pMenu;
    pMenu.SetID( "Menu_Other2" );
    pMenu.SetTitle( "其它测试2" );
    pMenu.AddItem( "显示当前/最大生命值" );
    pMenu.AddItem( "提升生命值" );
    pMenu.AddItem( "设置武器爆炸" );
    pMenu.AddItem( "查看配置信息" );
    pMenu.SetBack( true );
    pMenu.Display( pPlayer, -1 );
}

// 子选择 套装菜单
void Menu_Other_SuitMenu(CTerrorPlayer@ pPlayer){
if( pPlayer is null ) return;   
    Menu pMenu;
	pMenu.SetID( "Menu_Other_SuitMenu" );
    pMenu.SetTitle( "自定义套装菜单" );
    pMenu.AddItem( "手枪套" );
    pMenu.AddItem( "沙鹰套" );
    pMenu.AddItem( "近战套" );
    pMenu.AddItem( "莫斯喷子套" );
    pMenu.AddItem( "连喷套" );
    pMenu.AddItem( "弓箭套" );
    pMenu.AddItem( "地图默认" );
    pMenu.SetBack( true );
    pMenu.Display( pPlayer, -1 );            
}


// --------------------------------菜单处理--------------------------------


HookReturnCode OnMenuExecuted(CTerrorPlayer@ pPlayer, const string &in szID, int &in iValue)
{
    // 玩家商店菜单
    if( szID == "Menu_PlayerShop" ){
        switch(iValue){
            case 1:
            // 复活队友
                {
                    if( pPlayer.GetTeamNumber() == TEAM_SURVIVOR){
                        int price = 10*mf;
                        int score = pPlayer.GetScore() - price;
                        if( score>=0 ){
                            int respawnNum = 0;
                            array<int> playerList = Utils.CollectPlayers();
                            for(uint i=0;i<playerList.length();i++){
                                CTerrorPlayer@ player = ToTerrorPlayer(playerList[i]);
                                if(not (player.GetTeamNumber() == TEAM_SURVIVOR)){
                                    respawnPlayer(playerList[i]);
                                    pPlayer.AddScore(-price);
                                    respawnNum++;
                                }
                            }
                            if(respawnNum != 0){
                                Chat.PrintToChat(all,pPlayer.GetPlayerName()+"{hotpink}复活了"+respawnNum+"个队友，一个"+price+"块（Purchased resurrected teammates）");
                            }else{
                                Chat.PrintToChat(pPlayer,"{hotpink}没有队友死亡,不扣钱（No teammates died）");
                            }
                        }else{
                            Chat.PrintToChat(pPlayer,"{hotpink}钱不够（Not enough money）");
                        }
                    }else{
                        Chat.PrintToChat(pPlayer,"{hotpink}挂了不能买队友复活（Cannot purchase in a dead state）");
                    }
                }
                break;
            case 2:
            //复活自己
                {
                    if(pPlayer.GetTeamNumber() == TEAM_SURVIVOR){
                        Chat.PrintToChat(pPlayer,"{hotpink}没死复活个锤子");
                    }else{
                        int price = 25*mf;
                        int score = pPlayer.GetScore() - price;
                        if( score >= 0){
                            pPlayer.AddScore(-price);
                            // 调用复活功能中的复活，方便统一复活操作
                            respawnPlayer(pPlayer.entindex());
                            Chat.PrintToChat(pPlayer,pPlayer.GetPlayerName()+"{hotpink}购买了复活自己");
                        }else{
                            Chat.PrintToChat(pPlayer,"{hotpink}你的钱不够");
                        }
                    }
                }
                break;
            case 3:
            // 传送
                Open_PlayerShop_Tele(pPlayer);
                break;
            case 4:
            // 买医疗包
                {
                    int price = 8*mf;
                    int score = pPlayer.GetScore() - price;
                    if( score >= 0){
                        pPlayer.GiveWeapon("firstaid");
                        pPlayer.AddScore(-price);
                    }else{
                        Chat.PrintToChat(pPlayer,"{hotpink}你的钱不够");
                    }
                }
                break;
            case 5:
                {
                    int price = 6*mf;
                    int score = pPlayer.GetScore() - price;
                    if( score >= 0){
                        pPlayer.GiveWeapon("grenade");
                        pPlayer.AddScore(-price);
                    }else{
                        Chat.PrintToChat(pPlayer,"{hotpink}你的钱不够");
                    }
                }
                break;
            case 6:
            // 选择套装
                {
                    if(haveSuit)
                        Menu_SelectSuit(pPlayer);
                    else{
                        Chat.PrintToChat(pPlayer,"{hotpink}管理员未开启复活选枪");
                    }
                }
                break;
        }
    
    }else if(szID == "Menu_PlayerShop2"){
        switch(iValue){
            // 传送
            case 1: 
                Open_PlayerShop_Tele(pPlayer);
                break;
        }
    // 玩家传送选人菜单    
    }else if( Utils.StrContains("Menu_PlayerShop_Tele_Select", szID)){
        // 得到下标
        CASCommand@ arg = StringToArgSplit(szID, ";");
        int index =  Utils.StringToInt(arg.Arg(1));
        if(iValue == 8){
            // 如果是0则第一页，返回就是返回玩家商店
            if( index == 0 )
                MAINSHOP(pPlayer);
            else
                Menu_PlayerShop_Tele(pPlayer,index-7);
        }else if(iValue == 9){
            Menu_PlayerShop_Tele(pPlayer,index+7);
        }else if(iValue>0 && iValue<8){
            iValue = iValue + index;
            if( pPlayer.GetTeamNumber() == TEAM_SURVIVOR ){
                int pPlayerIndex = playerList[iValue-1];
                if(pPlayerIndex == pPlayer.entindex()){
                    Chat.PrintToChat(pPlayer,"{hotpink}你自己传你自己干嘛XD");
                }else{
                    CBasePlayer@ telePlayer = ToBasePlayer(pPlayerIndex);
                    Vector teleV = telePlayer.GetAbsOrigin();
                    pPlayer.SetAbsOrigin(teleV);
                    Chat.PrintToChat(all,"{hotpink}"+pPlayer.GetPlayerName()+"传送了自己到"+telePlayer.GetPlayerName());
                }
            }else{
                Chat.PrintToChat(pPlayer,"{hotpink}人都没了还传送个锤子");
            }
        }
    // 玩家复活套装选择
    }else if(szID == "Menu_SelectSuit"){
        int index = pPlayer.entindex();
        Chat.PrintToChat(all,""+playerSuitList[1]);
        switch( iValue ){
            case 1:
                playerSuitList[index-1] = 0;
                Chat.PrintToChat(pPlayer,"{hotpink}已成功切换套装为手枪套");
                break;
            case 2:
                playerSuitList[index-1] = 3;
                Chat.PrintToChat(pPlayer,"{hotpink}已成功切换套装为Mossberg喷子套");
                break;
            case 3:
                playerSuitList[index-1] = 2;
                Chat.PrintToChat(pPlayer,"{hotpink}已成功切换套装为近战套");
                break;
            case 4:
                playerSuitList[index-1] = 5;
                Chat.PrintToChat(pPlayer,"{hotpink}已成功切换套装为弓箭套");
                break;
            case 5:
                playerSuitList[index-1] = -1;
                Chat.PrintToChat(pPlayer,"{hotpink}已成功关闭复活套装");
                break;
        }
    // 超级管理员菜单
    }else if( szID == "superAdminMenu" ){
        switch( iValue ){
            case 1:
                Menu_Weapon(pPlayer);
                break;
            case 2:
                Menu_Zombie(pPlayer);
                break;
            case 3:
                Menu_Map(pPlayer);
                break;
            case 4:
                Menu_Prop(pPlayer);
                break;
            case 5:
                Open_Menu_Player(pPlayer);
                break;
            case 6:
                Menu_Server(pPlayer);
                break;
            case 7:
                Menu_Other(pPlayer);
                break;
        }
    }else if( szID == "Menu_Weapon" ){
        switch( iValue ){
            case 1:
				pPlayer.GiveWeapon("firstaid");
				break;
			case 2:
				pPlayer.GiveWeapon("Autoshotgun");
				break;
			case 3:
				pPlayer.GiveWeapon("ar15");
				break;
			case 4:
				pPlayer.GiveWeapon("handcannon");
				break;
			case 5:
				pPlayer.GiveWeapon("grenadelauncher");
				break;
            case 6:
                pPlayer.GiveWeapon("ammo");
                break;
            case 7:
                pPlayer.GiveWeapon("grenade");
                break;
            case 8:
                superAdminMenu( pPlayer );
                break;
            case 9:
                Menu_Weapon2(pPlayer);
                break;
        }
    }else if(szID == "Menu_Weapon2"){
        switch( iValue ){
            case 1:
                {
                    CBaseEntity@ Weapon = pPlayer.GetCurrentWeapon();
                    Chat.PrintToChat(pPlayer,"{hotpink}当前武器名："+Weapon.GetClassname());
                }
                break;
            case 2:
                pPlayer.GiveWeapon("fingergun");
                break;
            case 3:
                pPlayer.GiveWeapon("flamethrower");
                break;
            case 4:
                {
                    // 清空所有
                    pPlayer.StripEquipment( true );
                    // 给手机
                    pPlayer.GiveWeapon( "phone" );
                    // 给一个便携式手电
                    pPlayer.GiveWeapon( "plight" );
                    // 给扳手
                    pPlayer.GiveWeapon( "Wrench" );
                    // 给子弹
                    pPlayer.GiveWeapon( "ammo" );
                    // 给喷
                    pPlayer.GiveWeapon( "Mossberg" );  
                }
                break;
            case 8:
                Menu_Weapon( pPlayer );
                break;
        }
    }else if(szID == "Menu_Zombie"){
        switch( iValue ){
            case 1:
                Chat.PrintToChat( all,"{hotpink}当前世界僵尸数量:"+ Utils.CollectInfected().length());
                break;
            case 2:
                test_getZombieNum = !test_getZombieNum;
                getZombieNum();
                Chat.PrintToChat(all,"{hotpink}打开/关闭持续显示僵尸数量");
                break;
            case 3:
                if( ThePresident.IsHordeMode() ){
                    ThePresident.StopHordeMode();
                    Horde = false;
                    Chat.PrintToChat( all,"{hotpink}Horde模式已关闭" );                    
                }else{
                    ThePresident.BeginHordeMode();
                    Horde = true;
                    Chat.PrintToChat( all,"{hotpink}Horde模式已启动（全局锁人）" );
                }   
                break;
            case 4:
                ThePresident.CleanupNonVisibleZombies();
                Chat.PrintToChat( all,"{hotpink}已清除所有僵尸" );
                break;
            case 5:
                // 如果开了，就重新冻结
                if(test_freeze){
                    ThePresident.FreezeAllZombies(false);
                    ThePresident.FreezeAllZombies(true);
                    Chat.PrintToChat( all,"{hotpink}已重新冻结所有僵尸" );
                // 如果没冻结，冻结
                }else{
                    test_freeze = true;
                    ThePresident.FreezeAllZombies(true);
                    Chat.PrintToChat( all,"{hotpink}已冻结所有僵尸" );
                }
                break;
            case 6:
                test_freeze = false;
                ThePresident.FreezeAllZombies(false);
                Chat.PrintToChat( all,"{hotpink}已解冻所有僵尸" );
            case 8:
                superAdminMenu( pPlayer );
                break;
            case 9:
                Menu_Zombie2(pPlayer);
                break;
        }
    }else if( szID == "Menu_Zombie2" ){
        switch( iValue ){
            case 1:
                test_zombiespeed = !test_zombiespeed;
                if(test_zombiespeed){
                    Chat.PrintToChat( all,"{hotpink}已开启全跑尸（10）" );
                }else{
                    Chat.PrintToChat( all,"{hotpink}已关闭全跑尸" );
                }
                break;
            case 2:
                Chat.PrintToChat( all,"{hotpink}显示/关闭生成的僵尸速度" );
                test_checkZS = ! test_checkZS;
                break;
            case 8:
                Menu_Zombie( pPlayer );
                break;
        }
    }else if( szID == "Menu_Map" ){
        switch( iValue ){
            case 1:
                Open_Menu_Selct(pPlayer);
                break;
            case 2:
                {
                    ThePresident.ForceWinState( STATE_FAIL );
                    CASConVarRef@ mp_roundlimit = ConVar::Find( "mp_roundlimit" );
                    if ( mp_roundlimit is null ) return HOOK_CONTINUE;
                    int rounds = mp_roundlimit.GetInt();
                    if ( rounds <= 0 ) return HOOK_CONTINUE;
                    rounds++;
                    Engine.RunConsoleCommand("mp_roundlimit "+rounds);
                    Chat.PrintToChat(all,"{hotpink}管理员选择了重开");
                }
                break;
            case 3:
                Chat.PrintToChat( all,"{hotpink}当前地图类型为"+ThePresident.GetGameModeType() );
                Chat.PrintToChat( all,"{hotpink}地图类型参考|CT_DEV|"+CT_DEV+"|CT_OBJECTIVE|"+CT_OBJECTIVE+"|CT_EXTRACTION|"+CT_EXTRACTION+"|CT_FLATLINE|"+CT_FLATLINE+"|CT_HUNTED|"+CT_HUNTED);
                break;
            case 4:
                Chat.PrintToChat(all,"{hotpink}当前地图名为:"+Globals.GetCurrentMapName());
                break;
            case 8:
                superAdminMenu( pPlayer );
                break;
        }
    }else if(Utils.StrContains("Menu_Map_Select", szID)){
        // 得到下标
        CASCommand@ arg = StringToArgSplit(szID, ";");
        int index =  Utils.StringToInt(arg.Arg(1));
        // 选择值 + 页数起始值
        if( iValue>0 && iValue<8 ){
            iValue = iValue + index;
            // 传入菜单使用者id以及被被选择玩家id
            Engine.RunConsoleCommand("admin map "+mapList[iValue-1]);
        }else if( iValue == 8 ){
            if( index == 0 )
                Menu_Map(pPlayer);
            else
                Menu_Map_Select(pPlayer,index-7);
        }else if( iValue == 9 ){    
            Menu_Map_Select(pPlayer,index+7);
        }
    }else if( szID == "Menu_Prop" ){
        switch( iValue ){
            case 1:
                pPlayer.GiveWeapon("key");
                break;
            case 2:
                pPlayer.GiveWeapon("keycard");
                break;
            case 3:
                pPlayer.GiveWeapon("boltcutter");
                break;
            case 4:
                pPlayer.GiveWeapon("torch");
                break;
            case 5:
                pPlayer.GiveWeapon("plight");
                break;
            case 6:
                pPlayer.GiveWeapon("extinguisher");
                break;
            case 7:
                pPlayer.GiveWeapon("gasmask");
                break;
            case 8:
                superAdminMenu(pPlayer);
                break;
        }
    }else if( Utils.StrContains("Menu_Player", szID) ){
        // 得到下标
        CASCommand@ arg = StringToArgSplit(szID, ";");
        int index =  Utils.StringToInt(arg.Arg(1));
        // 选择值 + 页数起始值
        if( iValue>0 && iValue<8 ){
            iValue = iValue + index;
            if( false ){
                Chat.PrintToChat(pPlayer,"{hotpink}不要操作自己");
                return HOOK_CONTINUE;
            }else{
                // 传入菜单使用者id以及被被选择玩家id
                Player_Option(pPlayer,playerList[iValue-1]);
            }
        }else if( iValue == 8 ){
            if( index == 0 )
                superAdminMenu(pPlayer);
            else
                Menu_Player(pPlayer,index-7);
        }else if( iValue == 9 ){    
            Menu_Player(pPlayer,index+7);
        }
    }else if(Utils.StrContains("Player_Option1", szID)){
        // 得到值
        CASCommand@ arg = StringToArgSplit(szID, ";");
        int pPlayerIndex =  Utils.StringToInt(arg.Arg(1));
        CTerrorPlayer@ thatPlayer = ToTerrorPlayer(pPlayerIndex);
        switch(iValue){
            case 1:
                {
                    thatPlayer.SetMaxHealth(300);
                    thatPlayer.SetHealth(300);
                    Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"给"+thatPlayer.GetPlayerName()+"施加了血量增幅");
                }
                break;
            // 杀死玩家
            case 2:
                Engine.RunConsoleCommand( "admin slay !" + pPlayerIndex );
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"使用命令杀死了"+thatPlayer.GetPlayerName());
                break;
            // 将该玩家传送到自己
            case 3:
                {
                    Vector myVector = pPlayer.GetAbsOrigin();
                    thatPlayer.SetAbsOrigin(myVector);
                    Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"将"+thatPlayer.GetPlayerName()+"传送到自己");
                }
                break;
            // 发武器套装1
            case 4:
                // 清空所有
                thatPlayer.StripEquipment( true );
                // 给手机
                thatPlayer.GiveWeapon( "phone" );
                // 给一个便携式手电
                thatPlayer.GiveWeapon( "plight" );
                // 给子弹
                thatPlayer.GiveWeapon( "ammo" );
                // 给小刀
                thatPlayer.GiveWeapon( "kabar" );
                // 给手枪
                thatPlayer.GiveWeapon( "sig" );  
                break;
            // 添加管理员
            case 5:
                if( AdminSystem.PlayerHasAccessLevel(pPlayer, LEVEL_SUPERADMIN )){
                    AdminSystem.AddAdmin(thatPlayer);
                    if(AdminSystem.SetPlayerAccessLevel( thatPlayer, LEVEL_MODERATOR )){
                        Chat.PrintToChat(all,"{hotpink}超级管理员"+pPlayer.GetPlayerName()+"将"+thatPlayer.GetPlayerName()+"添加为管理员");
                    }
                }else{
                    Chat.PrintToChat(pPlayer,"{hotpink}只有超级管理员能添加管理员");
                }
                break;
            // 删除管理员
            case 6:
                if( AdminSystem.PlayerHasAccessLevel(pPlayer, LEVEL_SUPERADMIN )){
                    AdminSystem.RemoveAdmin(thatPlayer);
                    Chat.PrintToChat(all,"{hotpink}超级管理员"+pPlayer.GetPlayerName()+"将"+thatPlayer.GetPlayerName()+"从管理员列表中移除");
                }else{
                    Chat.PrintToChat(pPlayer,"{hotpink}只有超级管理员能删除管理员");
                }
                break;
            // 增加金钱
            case 7:
                thatPlayer.AddScore(100);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"给"+thatPlayer.GetPlayerName()+"加了100金币");
                break;
            case 8:
                Open_Menu_Player(pPlayer);
                break;
            case 9:
                Menu_Player_option2(pPlayer,pPlayerIndex);
                break;
        }
    }else if(Utils.StrContains("Player_Option2", szID)){
        // 得到值
        CASCommand@ arg = StringToArgSplit(szID, ";");
        int pPlayerIndex =  Utils.StringToInt(arg.Arg(1));
        CBasePlayer@ thatPlayer = ToBasePlayer(pPlayerIndex);
        switch( iValue ){
            case 1:
                if( AdminSystem.PlayerHasAccessLevel(pPlayer, LEVEL_SUPERADMIN )){
                    AdminSystem.Kick( thatPlayer, "你被踢了，如有异议，请加群说明情况" );
                }else{
                    Chat.PrintToChat(pPlayer,"{hotpink}只有超级管理员能直接踢人");
                }
                break;
            case 2:
                if( AdminSystem.PlayerHasAccessLevel(pPlayer, LEVEL_SUPERADMIN )){
                    AdminSystem.Ban(thatPlayer, 0, "你被ban了，如有异议，加群说明情况" );
                }else{
                    Chat.PrintToChat(pPlayer,"{hotpink}只有超级管理员能ban人");
                }
                break;
            case 8:
                Player_Option(pPlayer,pPlayerIndex);
                break;
        }
    }else if(szID == "Menu_Server"){
        switch( iValue ){
            // 开启作弊
            case 1:
                {
                    CASConVarRef@ sv_cheats = ConVar::Find( "sv_cheats" );
                    if(test_cheats){
                        sv_cheats.SetValue("0");
                        Chat.PrintToChat( all,"{hotpink}作弊关闭" );
                    }else{
                        sv_cheats.SetValue("1");
                        Chat.PrintToChat( all,"{hotpink}作弊开启" );
                    }
                    test_cheats = ! test_cheats;
                }
                break;
            // 无限体力
            case 2:
                {
                    CASConVarRef@ infiniteStamina= ConVar::Find( "sv_infinite_stamina" );
                    if( test_infiniteStamina ){
                        infiniteStamina.SetValue("0");
                        Chat.PrintToChat( all,"{hotpink}无限体力关闭" );
                    }else{
                        infiniteStamina.SetValue("1");
                        Chat.PrintToChat( all,"{hotpink}无限体力开启" );
                    }
                    test_infiniteStamina = ! test_infiniteStamina;
                }
                break;
            // 无限备弹
            case 3:
                {
                    CASConVarRef@ sv_infinite_collected_ammo = ConVar::Find( "sv_infinite_collected_ammo" );
                    if( test_infiniteCollectedAmmo ){
                        sv_infinite_collected_ammo.SetValue("0");
                        Chat.PrintToChat(pPlayer,"{hotpink}无限备弹关闭");
                    }else{
                        sv_infinite_collected_ammo.SetValue("1");
                        Chat.PrintToChat(pPlayer,"{hotpink}无限备弹开启");
                        //removeAllAmmo();
                        Chat.PrintToChat(all,"{hotpink}已清除地图所有子弹");
                    }
                    test_infiniteCollectedAmmo = ! test_infiniteCollectedAmmo;
                }
                break;
            // 无限主弹
            case 4:
                {
                    CASConVarRef@ sv_infinite_ammo = ConVar::Find( "sv_infinite_ammo" );
                    if( test_infiniteAmmo ){
                        sv_infinite_ammo.SetValue("0");
                        Chat.PrintToChat(pPlayer,"{hotpink}无限主弹关闭");
                    }else{
                        sv_infinite_ammo.SetValue("1");
                        Chat.PrintToChat(pPlayer,"{hotpink}无限主弹开启");
                        //removeAllAmmo();
                        Chat.PrintToChat(all,"{hotpink}已清除地图所有子弹");
                    }
                    test_infiniteAmmo = ! test_infiniteAmmo;
                }
                break;
            // 强制游戏胜利
            case 5:
                Engine.RunConsoleCommand("mp_roundlimit 1");
                ThePresident.ForceWinState(STATE_WIN);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"强制游戏获得胜利！");
                break;
            // 开启人机
            case 6:
                Engine.RunConsoleCommand( "bot_ai2 1" );
                Chat.PrintToChat(all,"开启人机");
                break;
            // 添加人机
            case 7:
                Engine.RunConsoleCommand( "bot_add" );
                Chat.PrintToChat(all,"{hotpink}添加人机");
                break;
            case 8:
                superAdminMenu(pPlayer);
                break;
        }
    }else if(szID == "Menu_Other"){
        switch( iValue ){
            case 1:
                test_dress = !test_dress;
                if( test_dress ){
                    Chat.PrintToChat( all,"{hotpink}僵尸装扮已开启" );
                }else{
                    Chat.PrintToChat( all,"{hotpink}僵尸装扮已关闭" );
                }
                break;
            case 2:
                openRespawn = ! openRespawn;
                if(openRespawn){
                    Chat.PrintToChat( all,"{hotpink}复活开启" );
                }else{
                    Chat.PrintToChat( all,"{hotpink}复活关闭" );
                }
                break;
            case 3:
                haveSuit = ! haveSuit;
                if(haveSuit){
                    Chat.PrintToChat( all,"{hotpink}开启自定义套装" );
                }else{
                    Chat.PrintToChat( all,"{hotpink}关闭自定义套装" );
                }
                break;
            case 4:
                pPlayer.AddScore(1000);
                Chat.PrintToChat( pPlayer,"{hotpink}加了一千分" );
                break;
            case 5:
                Menu_Other_SuitMenu(pPlayer);
                break;
            case 6:
                {
                    string ammo = "item_ammo_*";
                    CBaseEntity @pEnt = FindEntityByClassname( null, ammo );
                    while( pEnt !is null)
                    {
                        pEnt.SUB_Remove();
                        @pEnt = FindEntityByClassname( pEnt, ammo );
                    }
                }
                break;
            case 8:
                superAdminMenu(pPlayer);
                break;
            case 9:
                Menu_Other2(pPlayer);
                break;
        }
    }else if(szID == "Menu_Other2"){
        switch( iValue ){
            case 1:
                {
                    Chat.PrintToChat(pPlayer,"生命值为{hotpink}"+pPlayer.GetHealth()+"/"+pPlayer.GetMaxHealth());
                }
                break;
            case 2:
                {
                    pPlayer.SetMaxHealth(100000);
                    pPlayer.SetHealth(100000);
                    Chat.PrintToChat(pPlayer,"已成功设置新血量/上限");
                }
                break;
            case 3:
                {
                    CBaseEntity@ BaseWeapon = pPlayer.GetCurrentWeapon();
                    CTerrorWeapon@ Weapon = ToTerrorWeapon(BaseWeapon);
                    Chat.PrintToChat(pPlayer,"{hotpink}"+Weapon.GetMaxClip());
                    Weapon.UpgradeModule(SET,k_eExplosive);
                    Chat.PrintToChat(pPlayer,"{hotpink}已成功升级");
                }
                break;
            case 4:
                {
                    Chat.PrintToChat(all,"{hotpink}当前配置内容如下：");
                    Chat.PrintToChat(all,"{hotpink}configID:{green}"+configID);
                    Chat.PrintToChat(all,"{hotpink}openRespawn:{green}"+openRespawn);
                    Chat.PrintToChat(all,"{hotpink}haveSuit:{green}"+haveSuit);
                    Chat.PrintToChat(all,"{hotpink}second:{green}"+second);
                    Chat.PrintToChat(all,"{hotpink}playerHealth:{green}"+playerHealth);
                    Chat.PrintToChat(all,"{hotpink}shopOpen:{green}"+shopOpen);
                    Chat.PrintToChat(all,"{hotpink}shopType:{green}"+shopType);
                    Chat.PrintToChat(all,"{hotpink}test_infiniteCollectedAmmo:{green}"+test_infiniteCollectedAmmo);
                    Chat.PrintToChat(all,"{hotpink}test_infiniteStamina:{green}"+test_infiniteStamina);
                    Chat.PrintToChat(all,"{hotpink}Horde:{green}"+Horde);
                    Chat.PrintToChat(all,"{hotpink}zombieC:{green}"+zombieC);
                    Chat.PrintToChat(all,"{hotpink}test_zombiespeed:{green}"+test_zombiespeed);
                    Chat.PrintToChat(all,"{hotpink}test_dress:{green}"+test_dress);
                    Chat.PrintToChat(all,"{hotpink}mf:{green}"+mf);
                    Chat.PrintToChat(all,"{hotpink}hostName:{green}"+hostName);
                    Chat.PrintToChat(all,"{hotpink}mapcycle:{green}"+mapcycle);
                    Chat.PrintToChat(all,"{hotpink}Difficulty:{green}"+Difficulty);
                }
                break;
            case 8:
                Menu_Other(pPlayer);
                break;
        }
    }else if(szID == "Menu_Other_SuitMenu"){
        switch( iValue ){
            case 1:
                setPlayerSuit(0);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"已将复活装备设置为手枪套");
                break;
            case 2:
                setPlayerSuit(1);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"已将复活装备设置为沙鹰套");
                break;
            case 3:
                setPlayerSuit(2);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"已将复活装备设置为近战套");
                break;
            case 4:
                setPlayerSuit(3);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"已将复活装备设置为喷子套");
                break;
            case 5:
                setPlayerSuit(4);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"已将复活装备设置为连喷套");
                break;
            case 6:
                setPlayerSuit(5);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"已将复活装备设置为弓箭套");
                break;
            case 7:
                setPlayerSuit(-1);
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"已将复活装备设置为地图默认");
            case 8:
                Menu_Other(pPlayer);
                break;
        }
    }
    saveMoney(pPlayer);
    return HOOK_CONTINUE;
}

void getZombieNum(){
    Chat.PrintToChat(all,"当前世界僵尸数量："+Utils.CollectInfected().length());
    if(test_getZombieNum){
        Schedule::Task(5.0f,getZombieNum);
    }
}

void setPlayerSuit(int num){
    defaultSuit = num;
    playerSuitList = {defaultSuit,defaultSuit,defaultSuit,defaultSuit,
        defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,
        defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit,defaultSuit};
}

// ----------------------------------游戏玩法-----------------------------------------

// 游戏模式
int gamemode = 0;

// 地图开始
void ThePresident_OnMapStart(){
    // 获取游戏模式
    gamemode = ThePresident.GetGameModeType();
    // 如果是防守模式，把购买价格提高200倍
    if(gamemode == CT_FLATLINE){
        mf = 200;
    }else{
        mf = 1;
    }
    // 执行游戏命令
    // 服务器中文名
    Engine.RunConsoleCommand( "hostname "+hostName);
    // // 每多一个人，全局加多少丧尸  
    // Engine.RunConsoleCommand( "cx_spawn_new_player_nightmare 8" );
    // // 新区域开始时，全局增加僵尸数量
    // Engine.RunConsoleCommand( "cx_spawn_new_area_nightmare 6" );
    // 设置难度
    Engine.RunConsoleCommand( "Difficulty "+Difficulty );
    // 设置无法投票更改难度
    Engine.RunConsoleCommand( "sv_vote_issue_change_difficulty_allowed 0" );
    // 执行回合开始
    ThePresident_OnRoundStart();
}

// 回合开始
void ThePresident_OnRoundStart()
{
	gameover = false;
    // 仅AI丧尸（玩家死亡不会变丧尸）
    //Engine.RunConsoleCommand( "cg_zombie_ai_only 1" );
    // 无感染
    Engine.RunConsoleCommand( "cg_infection_disabled 1" );
    // 设置僵尸生成延迟
    Engine.RunConsoleCommand("cx_spawn_area_delay 0");
    // 重置玩家金币
    array<int> players = Utils.CollectPlayers();
    for(uint i =0;i < players.length();i++){
        CTerrorPlayer@ player = ToTerrorPlayer(players[i]);
        int score = player.GetScore();
        // 只将负债的清除为0
        if(score < 0){
            player.AddScore(-score);
        }
    }

    // 检查是否开启无限体力
    infiniteStamina();

    // 检查是否开启无限子弹
    sv_infinite_collected_ammo();

    // 检查是否开启僵尸锁人
    checkHorde();

    // 检查是否开启僵尸常量
    zombieConstant();

    // 保存重置
    isSave = false;

}

//-----------------------------------------------------------感染者死亡-------------------------------------------------------------//
HookReturnCode OnInfectedKilled(Infected@ pInfected, CTakeDamageInfo &in DamageInfo)
{

    CBaseEntity@ pAttacker = DamageInfo.GetAttacker();	//获取攻击者信息
    CTerrorPlayer@ pTerror = ToTerrorPlayer(pAttacker);	//转换攻击者为玩家属性

    // 给玩家加分
	pTerror.AddScore( 1 );

	return HOOK_CONTINUE;
}

//-----------------------------------------------------------防卫模式--------------------------------------------------------------

// 回合开始
HookReturnCode WaveStart(int &in iRound)
{
    // 实测在本方法内执行无限体力无效，但中途有效，故延时执行
    Schedule::Task(2.0f,infiniteStamina);
	return HOOK_CONTINUE;
}

//-----------------------------------------------------------其它方法--------------------------------------------------------------

// 无限体力
void infiniteStamina(){
    // 如果无限体力开启，执行一次（防止因为防卫模式把无限体力关了）
    if(test_infiniteStamina){
        CASConVarRef@ infiniteStamina= ConVar::Find( "sv_infinite_stamina" );
        infiniteStamina.SetValue("1");
        Chat.PrintToChat(all,"{hotpink}已自动开启无限体力");
    }
}

// 无限子弹
void sv_infinite_collected_ammo(){
    // 如果无限子弹开启，执行
    CASConVarRef@ infiniteStamina= ConVar::Find( "sv_infinite_collected_ammo" );
    if(test_infiniteCollectedAmmo){
        infiniteStamina.SetValue("1");
        Chat.PrintToChat(all,"{hotpink}已自动开启无限子弹");
        // 因为无法区别钉枪木板（也属于子弹），防止删除木板资源，故不再清除地图子弹
        //removeAllAmmo();
        //Chat.PrintToChat(all,"{hotpink}已清除地图所有子弹");
    }else{
        infiniteStamina.SetValue("0");
        Chat.PrintToChat(all,"{hotpink}已自动关闭无限子弹");
    }
}

// 实体掉落
HookReturnCode OnEntityDropped(CTerrorPlayer@ pPlayer, CBaseEntity@ pEntity)
{
    if(test_infiniteCollectedAmmo)
        //removeAllAmmo();
        removeDropAmmo(pEntity);
	return HOOK_CONTINUE;
}

// 清除掉落子弹
void removeDropAmmo(CBaseEntity@ pEntity){
    if(pEntity.ClassnameIs("item_ammo_*")){
        pEntity.SUB_Remove();
    }
}

// 清除所有子弹
void removeAllAmmo(){
    // 清除所有子弹
    string ammo = "item_ammo_*";
    CBaseEntity @pEnt = FindEntityByClassname( null, ammo );
    while( pEnt !is null)
    {
        pEnt.SUB_Remove();
        @pEnt = FindEntityByClassname( pEnt, ammo );
    }
}

// 锁人
void checkHorde(){
    if(Horde){
        ThePresident.BeginHordeMode();
        Chat.PrintToChat(all,"{hotpink}已自动开启Horde");
    }else{
        ThePresident.StopHordeMode();
        Chat.PrintToChat(all,"{hotpink}已自动关闭Horde");
    }
}

// 僵尸常量
void zombieConstant(){
    if(zombieC != 0){
        ThePresident.SetSpawnConstantFlags(ZSF_FORCED_NEAR_SPAWN);
        ThePresident.SetSpawnZombiesConstant(zombieC);
        Chat.PrintToChat(all,"{hotpink}已自动设置僵尸常量为"+zombieC);
    }
}


//-----------------------------当玩家逃脱--------------------------------
HookReturnCode OnPlayerEscape(CTerrorPlayer@ pPlayer)
{
    // If the player escapes, I need to make some records
    pPlayer.AddScore(50);
    Chat.PrintToChat(all,"已奖励玩家{green}["+pPlayer.GetPlayerName()+"]{gold}50金币");
    //Chat.PrintToChat(all,"执行了逃脱hook");
    updateEscape(pPlayer);
	return HOOK_CONTINUE;
}

void saveMoney(CTerrorPlayer@ pPlayer){
    string steamid = Utils.Steam64ToSteam32(pPlayer.GetSteamID64());
    string sql_saveMoney = "update `record` set money = "+pPlayer.GetScore()+" where steamid = '"+steamid+"';";
    SQL::SendQuery( gMainConnection, sql_saveMoney);
}

void updateEscape(CTerrorPlayer@ pPlayer){
    string steamid = Utils.Steam64ToSteam32(pPlayer.GetSteamID64());
    string sql_updateEscapeCount = "update `record` set escapeCount = escapeCount+1 where steamid = '"+steamid+"';";
    SQL::SendQuery( gMainConnection, sql_updateEscapeCount);
}

// 是否已保存
bool isSave = false;

// 当玩家抵达安全区
HookReturnCode OnPlayerReachSafeZone(CTerrorPlayer@ pPlayer)
{
    Chat.PrintToChat(all,"玩家{green}"+pPlayer.GetPlayerName()+"抵达安全区");
    if( !isSave ){
        saveALLMoney();
        isSave = true;
    }
	return HOOK_CONTINUE;
}

// 当玩家离开安全区
HookReturnCode OnPlayerLeftSafeZone(CTerrorPlayer@ pPlayer)
{
    Chat.PrintToChat(all,"玩家离开安全区");
	return HOOK_CONTINUE;
}

// 回合终止时
HookReturnCode OnTerminateRound(int iTeam)
{
    saveALLMoney();

	return HOOK_CONTINUE;
}

void saveALLMoney(){
    // 保存所有玩家的当前金币
    playerList = Utils.CollectPlayers();
    for(uint i=0;i<playerList.length();i++){
        CTerrorPlayer@ pPlayer = ToTerrorPlayer(playerList[i]);
        string steamid = Utils.Steam64ToSteam32(pPlayer.GetSteamID64());
        string sql_saveMoney = "update `record` set money = "+pPlayer.GetScore()+" where steamid = '"+steamid+"';";
        SQL::SendQuery( gMainConnection, sql_saveMoney);
    }
    Chat.PrintToChat(all,"{green}[数据库]:{hotpink}已保存所有玩家金币值");
}